#include <iostream>
#include <cstring>
#include <string>
#include <fcntl.h>
#include <assert.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
using namespace std;

#define LOGNAME "./log/log.txt" //所有日志
#define INFONAME "./log/info.txt" //常规
#define WARINGNAME "./log/waring.txt" //警告
#define ERRORNAME "./log/error.txt" //错误
#define FATOLNAME "./log/fatol.txt" //致命
#define FILEMOD 0666
#define BUFFSIZE 1024
char buff[BUFFSIZE];
const char* WDAY[] = {"天","一","二","三","四","五","六"};
const char* LEVEL[] = {"info","waring","error","fatol","debug"};

typedef void (*funcptr)();
void Info();void Waring();void Error();void Fatol();void Debug();
funcptr func[] = {&Info,&Waring,&Error,&Fatol,&Debug};

//根据日志等级和用户自定义内容,生成日志字符串到buff
void GetBuff(const char* level,const char* msg,const char* file,const int line){
    time_t timep;
    time(&timep);
    struct tm* p = localtime(&timep);
    snprintf(buff,BUFFSIZE,"[%s][%d-%d-%d %d:%d:%d][星期%s] : in \"%s\", %s, line:%d\n\0",
        level,p->tm_year+1900,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec,WDAY[p->tm_wday],
        file, msg, line);
}
//按追加方式打开文件
int OpenFile(const char* filename){
    int fd = open(filename,O_APPEND|O_CREAT|O_WRONLY,FILEMOD);
    if(fd == -1){
        mkdir("./log",0766);
        fd = open(filename,O_APPEND|O_CREAT|O_WRONLY,FILEMOD);
        assert(fd>=0);
    }
    return fd;
}
//把全局buff内容写入指定文件
void WriteFile(int fd){
    if(write(fd,buff,strlen(buff)) < 0){
        perror("write");
        exit(errno);
    }
}

//外部函数调用接口, 格式 log("等级","自定义类容",__FILE__,__LINE__)
void log(const char* level,const char* msg,const char* file,const int line){
    GetBuff(level,msg,file,line);
    for(int i=0;i<5;++i){
        if(strcmp(level,LEVEL[i]) == 0){
            func[i]();
            if(i<4){//不是debug日志,往总日志写入一条
                int fd = OpenFile(LOGNAME);
                WriteFile(fd);
                close(fd);
            }
            break;
        }
    }
}


void Info(){
    int fd = OpenFile(INFONAME);
    WriteFile(fd);
    close(fd);
}

void Waring(){
    int fd = OpenFile(WARINGNAME);
    WriteFile(fd);
    close(fd);
}
void Error(){
    int fd = OpenFile(ERRORNAME);
    WriteFile(fd);
    close(fd);
}
void Fatol(){
    int fd = OpenFile(FATOLNAME);
    WriteFile(fd);
    close(fd);
}
void Debug(){
    WriteFile(1);
}
